import fs from "fs";
import path from "path";
import pLimit from "p-limit";
import cliProgress from "cli-progress";
import {
  sleep,
  getFollowingPageData2,
  getImageUrl2,
} from "../../utils/canvasUtils.js";
import {
  axiosInstance as axios,
  fileUtils,
  type ConfigCanvasPhoto,
} from "./axios.js";
import {
  CardItem,
  LastPageMap,
  LastTokenMap,
  img,
  ImageInfo,
} from "./types.js";

main()

async function main() {
  try {
    const config: ConfigCanvasPhoto = fileUtils.config;
    const lastTokenMap: LastTokenMap = config.lastTokenMap;
    const lastPageMap: LastPageMap = config.lastPageMap;

    for (const startToken in lastTokenMap) {
      console.log(
        `正在接续获取${startToken}的所有Token,目前是第${
          lastPageMap[startToken].page! + 1
        }页`
      );

      let lastToken = (await scratchToken(lastTokenMap[startToken], startToken))
        .token;
      if (!lastToken) {
        console.log(`获取${startToken}的图片结束`);
        continue;
      }
      console.log(`获取到${startToken}的Token: ${lastToken}`);
      console.log(`获取${startToken}的图片结束`);
    }
  } catch (e) {
    fileUtils.logError(e);
    process.exit(1);
  }
}

//====================通过【1】通过请求获取Token=================
//通过给定的token，循环下拉式获取后续的Token，直到没有更多Token为止
async function scratchToken(
  token: string,
  path: string
): Promise<{ data: CardItem[]; token: string }> {
  const currentConfig: any = fileUtils.config;
  const lastPageMap: any = currentConfig.lastPageMap;
  const lastPage = lastPageMap[path].page;
  const end = lastPageMap[path].end;
  let data = [] as CardItem[];

  for (let i = 1 + lastPage; i < 98; i++) {
    if (i >= 98) {
      break;
    }
    console.log(i);
    const res = await getFollowingPageData2(token, 100);
    const total = res.total / 100;
    if (i > total) {
      break;
    }
    if(i>end){
      break;
    }
    const dataList: ImageInfo[] = res.urlList;

    const urlList = dataList.map((item) => {
      return {
        url: item.url,
        token: item.token,
      };
    });
    console.log("获取到一批图片url，准备下载图片.");
    sleep(1000, 3000);
    await downloadImgs(path, urlList);
    token = res.continuationToken;
    lastTokenHandle(path, token, i);
  }
  return { data, token };
}

//====================【2】通过Token获取图片url====================
//纯函数： 给每张卡片的token，请求获取图片url
export async function getAllImageUrl(tokens: CardItem[]) {
  let index = 0;
  
  let data: any[] = [];
  while (index < tokens.length) {
    try {
      const res = await getImageUrl2(tokens[index].token);
      data = data.concat(res);
      index++;
      if (index === tokens.length) {
        const urlList: img[] = data.map(item => ({
          url: item.url,
          token: item.token
        }));
        return urlList;
      }
    } catch (err) {
      console.log(err, "重试下载");
      await new Promise((resolve) => setTimeout(resolve, 10000));
    }
  }
}

// ===================== 【3】下载图片到本地 =====================
//纯函数： 下载图片，并重试三次
async function downloadImgWithRetry(
  imgUrl: string,
  filePath: string,
  retries = 3
) {
  // 如果文件已经存在，则直接返回
  if (fs.existsSync(filePath)) {
    return;
  }
  try {
    const res = await axios.get(imgUrl, {
      responseType: "arraybuffer",
    });
    fs.writeFileSync(filePath, Buffer.from(res.data));
  } catch (error) {
    if (retries > 0) {
      console.log(`⚠️ 图片下载失败，重试中...`);
      sleep(1000, 1000);
      return downloadImgWithRetry(imgUrl, filePath, retries - 1);
    } else {
      fileUtils.logError(error);
    }
  }
}

//图片下载函数的封装
async function downloadImgs(keyword: string, imgUrls: img[]) {
  const res = await getType();
  console.log(`🔥 开始下载 ${imgUrls.length} 张图片`);
  const rowdir = path.resolve(fileUtils.outDirPath, res);
  const dir = path.resolve(rowdir, keyword);
  fs.mkdirSync(dir, { recursive: true }); //确保目录存在
  const limit = pLimit(fileUtils.config.concurrency); // 限制下载并发

  // 初始化进度条
  const progressBar = new cliProgress.SingleBar({}, cliProgress.Presets.rect);
  progressBar.start(imgUrls.length, 0);
  const promises = imgUrls.map(async (imgUrl) => {
    //文件名处理
    const filePath = await fileNameHandle(imgUrl.token, dir);
    return limit(async () => {
      await downloadImgWithRetry(imgUrl.url, filePath);
      progressBar.increment(); // 更新进度条
    });
  });

  await Promise.all(promises);
  progressBar.stop(); // 停止进度条
}

//====================【4】参数处理===========================
//文件名处理函数
const fileNameHandle = async (imgUrl: string, dir: string): Promise<string> => {
  const fileName = `${imgUrl}.jpg`;
  const filePath = `${dir}/${fileName}`;
  return filePath;
};
//下载参数处理函数
const lastTokenHandle = (path: string, token: string, index: number) => {
  const currentConfig: any = fileUtils.config;
  const userToken = token || "";
  if (!currentConfig.lastTokenMap) {
    currentConfig.lastTokenMap = {};
  }
  if (!currentConfig.lastPageMap) {
    currentConfig.lastPageMap = {};
  }
  currentConfig.lastPageMap[path].page = index;
  currentConfig.lastTokenMap[path] = userToken;
  fileUtils.writeConfig(currentConfig);
};
//获取下载类型
const getType = async () => {
  const config = fileUtils.config;
  const type = config.type;
  const res = `${type}/`;
  return res;
};




